﻿/*********************************
 $Archive: /Ease/src/Components/Vbyte.SharpOrm/TableEntryConverter.cs $
 $Author: qinjunIt@gmail.com $
 $Modtime: 09-03-20 10:11 $
 $Revision: 43 $
********************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Web.Script.Serialization;
using System.Xml.Serialization;
using Vbyte.DataSource.Cache;

namespace Vbyte.SharpOrm
{
    /// <summary>
    /// 实体映射的Javascript转换
    /// </summary>
	public class TableEntryConverter : JavaScriptConverter
	{

        private ReadOnlyCollection<Type> _supportedTypes = new ReadOnlyCollection<Type>(
            new Type[] { typeof(TableEntry) 
          });

        /// <summary>
        /// 当在派生类中重写时，将所提供的字典转换为指定类型的对象。
        /// </summary>
        /// <param name="dictionary">作为名称/值对存储的属性数据的 <see cref="T:System.Collections.Generic.IDictionary`2"/> 实例。</param>
        /// <param name="type">所生成对象的类型。</param>
        /// <param name="serializer"><see cref="T:System.Web.Script.Serialization.JavaScriptSerializer"/> 实例。</param>
        /// <returns>反序列化的对象。</returns>
        public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
        {
            if (type.IsAbstract)
                throw new NotSupportedException("不能反序列化为抽象类型！");

            object obj = Activator.CreateInstance(type);
            foreach (string key in dictionary.Keys)
            {
                PropertyInfo[] Properties = GenericCache<PropertyInfo[]>.Get(type.FullName, () => type.GetProperties());
                foreach (PropertyInfo pi in Properties)
                {
                    pi.SetValue(obj, Convert.ChangeType(dictionary[pi.Name], pi.PropertyType), null);
                }
            }
            return obj;
        }

        /// <summary>
        /// 当在派生类中重写时，生成名称/值对的字典。
        /// </summary>
        /// <param name="obj">要序列化的对象。</param>
        /// <param name="serializer">负责序列化的对象。</param>
        /// <returns>一个对象，包含表示该对象数据的键/值对。</returns>
        public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
        {
            Type t = obj.GetType();
            TableEntry entry = obj as TableEntry;
            if (entry == null)
            {
                throw new ArgumentException("数据类型必须基于TableEntry。", "obj");
            }

            Dictionary<string, object> dictionary = new Dictionary<string, object>();
            object propValue = null;

            #region 设置实例的相关属性
            PropertyInfo[] Properties = GenericCache<PropertyInfo[]>.Get(t.FullName, () => t.GetProperties());
            foreach (PropertyInfo pi in Properties)
            {
                #region 临时忽略属性
                if (entry.SerializeOnlyList != null && entry.SerializeOnlyList.Length > 0)
                {
                    if (!OrmHelper.StringArrayContains(entry.SerializeOnlyList, pi.Name))
                    {
                        continue;
                    }
                }

                if (entry.SerializeIgnoreList != null && entry.SerializeIgnoreList.Length >0)
                {
                    if (OrmHelper.StringArrayContains(entry.SerializeIgnoreList, pi.Name))
                    {
                        continue;
                    }
                }
                #endregion

                //固定忽略
                if (OrmHelper.HasAttribute(pi, typeof(XmlIgnoreAttribute), true))
                {
                    continue;
                }

                if (OrmHelper.HasAttribute(pi, typeof(ScriptIgnoreAttribute), true))
                {
                    continue;
                }

                propValue = pi.GetGetMethod().Invoke(obj, null);
                //if (propValue != null)
                //{
                //    //System.Diagnostics.Debug.WriteLine(pi.PropertyType);
                //    if (!SqlBindHelper.IsInstanceBindDefaultValue(pi.PropertyType, propValue))
                //    {
                //        dictionary.Add(pi.Name, propValue);
                //    }
                //}
                //else
                //{
                    dictionary.Add(pi.Name, propValue);
                //}
            }
            #endregion

            #region 对不在集合中的扩展泛型实例获取扩展数据
            if (!entry.IsInCollection)
            {
                Type CheckType = typeof(IEntryExtension<>);
                //检查是否实现接口IEntryExtension<E>
                if (t.GetInterface(CheckType.Namespace + "." + CheckType.Name, true) != null)
                {
                    try
                    {
                        DictionaryEntry[] DE = t.GetMethod("GetExtenEntryArray").Invoke(obj, null) as DictionaryEntry[];
                        foreach (DictionaryEntry e in DE)
                        {
                            dictionary.Add(e.Key.ToString(), e.Value);
                        }
                    }
                    catch (Exception) { }
                }
            }
            #endregion

            return dictionary;
        }

        /// <summary>
        /// 当在派生类中重写时，获取受支持类型的集合。
        /// </summary>
        /// <value></value>
        /// <returns>一个实现 <see cref="T:System.Collections.Generic.IEnumerable`1"/> 的对象，用于表示转换器支持的类型。</returns>
        public override IEnumerable<Type> SupportedTypes
        {
            get
            {
                return this._supportedTypes;
            }
        }

    }
}